//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================



using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Xml;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Serialization;

using LitwareHR.Portfolio.Gateways;
using LitwareHR.Recruiting.Workflows;
using LitwareHR.Recruiting.Workflows.Activities;
using Shp.Runtime.Contract;
using LitwareHR.PrivateApp.Presenters.Properties;

namespace LitwareHR.PrivateApp.Presenters.ConfigCusto.Process
{
    public class AddWorkflowPresenter
    {
        IAddWorkflowView _view;

        public AddWorkflowPresenter(IAddWorkflowView view)
        {
            _view = view;
        }

        public void OnViewLoaded(string tenantAlias)
        {
            _view.Steps = new List<WorkflowStep>();
            _view.Roles = new List<string>(AuthenticationGateway.GetRoles(tenantAlias));
            _view.StepTypes = GetStepTypes();
            _view.ShowSteps();
        }

        public Dictionary<string, string> GetStepTypes()
        {
                Dictionary<string, string> types = new Dictionary<string, string>();
                types.Add(typeof(InterviewActivity).ToString(), Constants.Ruleset.InterviewStep);
                types.Add(typeof(NegotiationActivity).ToString(), Constants.Ruleset.NegotiationStep);
                types.Add(typeof(ResultActivity).ToString(), Constants.Ruleset.ResultStep);
                return types;
        }

        public void OnAddStep()
        {
            _view.UpdateSteps();
            _view.Steps.Add(new WorkflowStep(Constants.Ruleset.InterviewStep, typeof(InterviewActivity).ToString(), null));
            _view.ShowSteps();
        }

        public void OnRemoveStep(int index)
        {
            _view.Steps.RemoveAt(index);
            _view.ShowSteps();
        }

        public void OnMoveStepUp(int index)
        {
            WorkflowStep step = _view.Steps[index];
            if (step != null && index > 0)
            {
                _view.Steps.RemoveAt(index);
                _view.Steps.Insert(index - 1, step);
            }
            _view.ShowSteps();
        }

        public void OnMoveStepDown(int index)
        {
            WorkflowStep step = _view.Steps[index];
            if (step != null && index < _view.Steps.Count - 1)
            {
                _view.Steps.RemoveAt(index);
                _view.Steps.Insert(index + 1, step);
            }
            _view.ShowSteps();
        }

        public void OnSaveWorkflow()
        {
            _view.UpdateSteps();
            try
            {
                ValidateWorkflow();
                EvaluationProcess evaluationProcess = CreateEvaluationProcess();
                string xoml = SerializeProcess(evaluationProcess);
                WorkflowGateway.AddWorkflowDef(_view.ProcessName, xoml);
            }
            catch (Exception ex)
            {
                _view.ShowErrorMessage(ex.Message);
            }
        }


        private void ValidateWorkflow()
        {
            bool nameRepeatedError = false;
            bool nameError = false;
            string errorMessage = string.Empty;
            List<string> names = new List<string>();
            foreach (WorkflowStep step in _view.Steps)
            {
                if (names.Contains(step.Name))
                {
                    if (!nameRepeatedError)
                    {
                        errorMessage = string.Concat(errorMessage, Resources.StepNameRepeatedErrorMessage);
                    }
                    nameRepeatedError = true;
                }
                if (step.Name.Contains(" "))
                {
                    if (!nameError)
                    {
                        errorMessage = string.Concat(errorMessage, Resources.InvalidStepNameErrorMessage);
                    }
                    nameError = true;

                }
                names.Add(step.Name);
            }
            if (nameRepeatedError || nameError)
            {
                throw new Exception(errorMessage);
            }

        }

        private EvaluationProcess CreateEvaluationProcess()
        {
            EvaluationProcess evaluationProcess = new EvaluationProcess();
            evaluationProcess.Name = _view.ProcessName;
            ActivityCollection activities = new ActivityCollection(evaluationProcess);
            foreach (WorkflowStep step in _view.Steps)
            {
                HumanInteractionActivity activity = ProcessStepToActivity(step);
                evaluationProcess.Activities.Add(activity);
            }
            return evaluationProcess;
        }

        private string SerializeProcess(CompositeActivity activity)
        {
            CompositeActivityMarkupSerializer serializer = new CompositeActivityMarkupSerializer();
            StringWriter writer = new StringWriter();
            XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
            xmlWriterSettings.OmitXmlDeclaration = true;
            XmlWriter xmlWriter = XmlWriter.Create(writer, xmlWriterSettings);
            serializer.Serialize(xmlWriter, activity);

            return writer.ToString();
        }

        private HumanInteractionActivity ProcessStepToActivity(WorkflowStep step)
        {
            HumanInteractionActivity activity = typeof(HumanInteractionActivity).Assembly.CreateInstance(step.Type) as HumanInteractionActivity;

            activity.Name = step.Name;

            activity.WorkflowRoles = new WorkflowRoleCollection();
            CustomRole role = new CustomRole();
            role.Name = step.Role;
            activity.WorkflowRoles.Add(role);

            return activity;
        }
    }
}
